home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / AudioSource.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  5.8 KB  |  205 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20.  
  21. #include <windows.h>
  22. #include <vfw.h>
  23.  
  24. #include "AudioSource.h"
  25. #include "AVIReadHandler.h"
  26.  
  27. AudioSourceWAV::AudioSourceWAV(char *szFile, LONG inputBufferSize) {
  28.     MMIOINFO mmi;
  29.  
  30.     memset(&mmi,0,sizeof mmi);
  31.     mmi.cchBuffer    = inputBufferSize;
  32.     hmmioFile        = mmioOpen(szFile, &mmi, MMIO_READ | MMIO_ALLOCBUF);
  33. }
  34.  
  35. AudioSourceWAV::~AudioSourceWAV() {
  36.     mmioClose(hmmioFile, 0);
  37. }
  38.  
  39. BOOL AudioSourceWAV::init() {
  40.     if (!hmmioFile) return FALSE;
  41.  
  42.     chunkRIFF.fccType = mmioFOURCC('W','A','V','E');
  43.     if (MMSYSERR_NOERROR != mmioDescend(hmmioFile, &chunkRIFF, NULL, MMIO_FINDRIFF))
  44.         return FALSE;
  45.  
  46.     chunkDATA.ckid = mmioFOURCC('f','m','t',' ');
  47.     if (MMSYSERR_NOERROR != mmioDescend(hmmioFile, &chunkDATA, &chunkRIFF, MMIO_FINDCHUNK))
  48.         return FALSE;
  49.  
  50.     if (!allocFormat(chunkDATA.cksize)) return FALSE;
  51.     if (chunkDATA.cksize != mmioRead(hmmioFile, (char *)getWaveFormat(), chunkDATA.cksize))
  52.         return FALSE;
  53.  
  54.     if (MMSYSERR_NOERROR != mmioAscend(hmmioFile, &chunkDATA, 0))
  55.         return FALSE;
  56.  
  57.     chunkDATA.ckid = mmioFOURCC('d','a','t','a');
  58.     if (MMSYSERR_NOERROR != mmioDescend(hmmioFile, &chunkDATA, &chunkRIFF, MMIO_FINDCHUNK))
  59.         return FALSE;
  60.  
  61.     bytesPerSample    = getWaveFormat()->nBlockAlign; //getWaveFormat()->nAvgBytesPerSec / getWaveFormat()->nSamplesPerSec;
  62.     lSampleFirst    = 0;
  63.     lSampleLast        = chunkDATA.cksize / bytesPerSample;
  64.     lCurrentSample    = 0;
  65.  
  66.     streamInfo.fccType                    = streamtypeAUDIO;
  67.     streamInfo.fccHandler                = 0;
  68.     streamInfo.dwFlags                    = 0;
  69.     streamInfo.wPriority                = 0;
  70.     streamInfo.wLanguage                = 0;
  71.     streamInfo.dwInitialFrames            = 0;
  72.     streamInfo.dwScale                    = bytesPerSample;
  73.     streamInfo.dwRate                    = getWaveFormat()->nAvgBytesPerSec;
  74.     streamInfo.dwStart                    = 0;
  75.     streamInfo.dwLength                    = chunkDATA.cksize / bytesPerSample;
  76.     streamInfo.dwSuggestedBufferSize    = 0;
  77.     streamInfo.dwQuality                = 0xffffffff;
  78.     streamInfo.dwSampleSize                = bytesPerSample;
  79.  
  80.     return TRUE;
  81. }
  82.  
  83. int AudioSourceWAV::_read(LONG lStart, LONG lCount, LPVOID buffer, LONG cbBuffer, LONG *lBytesRead, LONG *lSamplesRead) {
  84.     LONG lBytes = lCount * bytesPerSample;
  85.     
  86.     if (buffer) {
  87.         if (lStart != lCurrentSample)
  88.             if (-1 == mmioSeek(hmmioFile, chunkDATA.dwDataOffset + bytesPerSample*lStart, SEEK_SET))
  89.                 return AVIERR_FILEREAD;
  90.  
  91.         if (lBytes != mmioRead(hmmioFile, (char *)buffer, lBytes))
  92.             return AVIERR_FILEREAD;
  93.  
  94.         lCurrentSample = lStart + lCount;
  95.     }
  96.  
  97.     *lSamplesRead = lCount;
  98.     *lBytesRead = lBytes;
  99.  
  100.     return AVIERR_OK;
  101. }
  102.  
  103. ///////////////////////////
  104.  
  105. AudioSourceAVI::AudioSourceAVI(IAVIReadHandler *pAVI) {
  106.     pAVIFile    = pAVI;
  107.     pAVIStream    = NULL;
  108. }
  109.  
  110. AudioSourceAVI::~AudioSourceAVI() {
  111.     if (pAVIStream)
  112.         delete pAVIStream;
  113. }
  114.  
  115. BOOL AudioSourceAVI::init() {
  116.     LONG format_len;
  117.  
  118.     pAVIStream = pAVIFile->GetStream(streamtypeAUDIO, 0);
  119.     if (!pAVIStream) return FALSE;
  120.  
  121.     if (pAVIStream->Info(&streamInfo, sizeof streamInfo))
  122.         return FALSE;
  123.  
  124.     pAVIStream->FormatSize(0, &format_len);
  125.  
  126.     if (!allocFormat(format_len)) return FALSE;
  127.  
  128.     if (pAVIStream->ReadFormat(0, getFormat(), &format_len))
  129.         return FALSE;
  130.  
  131.     lSampleFirst = pAVIStream->Start();
  132.     lSampleLast = pAVIStream->End();
  133.  
  134.     return TRUE;
  135. }
  136.  
  137. void AudioSourceAVI::Reinit() {
  138.     pAVIStream->Info(&streamInfo, sizeof streamInfo);
  139.     lSampleFirst = pAVIStream->Start();
  140.     lSampleLast = pAVIStream->End();
  141. }
  142.  
  143. bool AudioSourceAVI::isStreaming() {
  144.     return pAVIStream->isStreaming();
  145. }
  146.  
  147. void AudioSourceAVI::streamBegin(bool fRealTime) {
  148.     pAVIStream->BeginStreaming(lSampleFirst, lSampleLast, fRealTime ? 1000 : 2000);
  149. }
  150.  
  151. void AudioSourceAVI::streamEnd() {
  152.     pAVIStream->EndStreaming();
  153.  
  154. }
  155.  
  156. BOOL AudioSourceAVI::_isKey(LONG lSample) {
  157.     return pAVIStream->IsKeyFrame(lSample);
  158. }
  159. int AudioSourceAVI::_read(LONG lStart, LONG lCount, LPVOID lpBuffer, LONG cbBuffer, LONG *lpBytesRead, LONG *lpSamplesRead) {
  160.     int err;
  161.     long lBytes, lSamples;
  162.  
  163.     // There are some video clips roaming around with truncated audio streams
  164.     // (audio streams that state their length as being longer than they
  165.     // really are).  We use a kludge here to get around the problem.
  166.  
  167.     err = pAVIStream->Read(lStart, lCount, lpBuffer, cbBuffer, lpBytesRead, lpSamplesRead);
  168.  
  169.     if (err != AVIERR_FILEREAD)
  170.         return err;
  171.  
  172.     // Suspect a truncated stream.
  173.     //
  174.     // AVISTREAMREAD_CONVENIENT will tell us if we're actually encountering a
  175.     // true read error or not.  At least for the AVI handler, it returns
  176.     // AVIERR_ERROR if we've broached the end.  
  177.  
  178.     *lpBytesRead = *lpSamplesRead = 0;
  179.  
  180.     while(lCount > 0) {
  181.         err = pAVIStream->Read(lStart, AVISTREAMREAD_CONVENIENT, NULL, 0, &lBytes, &lSamples);
  182.  
  183.         if (err)
  184.             return 0;
  185.  
  186.         if (!lSamples) return AVIERR_OK;
  187.  
  188.         if (lSamples > lCount) lSamples = lCount;
  189.  
  190.         err = pAVIStream->Read(lStart, lSamples, lpBuffer, cbBuffer, &lBytes, &lSamples);
  191.  
  192.         if (err)
  193.             return err;
  194.  
  195.         lpBuffer = (LPVOID)((char *)lpBuffer + lBytes);
  196.         cbBuffer -= lBytes;
  197.         lCount -= lSamples;
  198.  
  199.         *lpBytesRead += lBytes;
  200.         *lpSamplesRead += lSamples;
  201.     }
  202.  
  203.     return AVIERR_OK;
  204. }
  205.